package com.engine.modules.vector.mapper;

import com.engine.common.exception.SystemTableException;
import com.engine.common.util.BasicParamUtil.ByteArryUtil;
import com.engine.init.Globle;
import com.engine.init.entity.GroupPropertiesEntity;
import com.engine.init.entity.TableToGroupEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Slf4j
public class VectorTilesMapper {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * @Description TODO 获取矢量切片
     */
    public byte[] selectTileByXYZ(int z, int x, int y, String tableName, String layerName, String authCo) {
        if (Globle.TablePropertiesMap.get(tableName) == null )
            throw new SystemTableException("tableName="+tableName+",数据库中表不存在或未添加进数据目录");
        if (!Globle.TablePropertiesMap.get(tableName).getTableType().equals("Vector"))
            throw new SystemTableException("表数据格式错误");
        int minz = (int) Globle.TablePropertiesMap.get(tableName).getMinz();
        int maxz = (int) Globle.TablePropertiesMap.get(tableName).getMaxz();
        if (z < minz || z > maxz)
            return null;
        String whereSql="";
        if(Globle.TablePropertiesMap.get(tableName).getZoomControl())
            whereSql+=" AND zmin<=" + z;
        if(Globle.TablePropertiesMap.get(tableName).getPermissionControl())
            whereSql+=" AND (LEFT(pac," + authCo.length() + ")='" + authCo + "' OR pac IS NULL)";
        String general_columns = Globle.TablePropertiesMap.get(tableName).getGeneralColumns();
        String sys_columns = Globle.TablePropertiesMap.get(tableName).getSysColumns();
        String colums = general_columns + "," + sys_columns;
        String bbox="st_transform(TileBBox(" + z + "," + x + "," + y + "),"+ Globle.TablePropertiesMap.get(tableName).getSrid()+")";
//        log.debug("tableName"+tableName+"|x:" + x + "|y:" + y + "|z:" + z);
        String sql = "SELECT ST_AsMVT(tile,'" + layerName + "',4096,'geom') tile FROM (SELECT " + colums + "," +
                "ST_AsMVTGeom(w.geom,"+bbox+",4096, 256, true) AS geom FROM " +
                "(SELECT " + colums + ",geom FROM " + tableName + " WHERE "+bbox+
                " && geom AND del_flag='0' "+whereSql+") w WHERE " +
                "geom IS NOT NULL) AS  tile WHERE tile.geom IS NOT NULL";
        byte[] configxml = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> rs.getBytes(1));
        return configxml;
    }


    /**
     * @Description TODO 先查切片属于哪几个地区，然后根据地区查对应表，查出来先拼接再组成切片
    	* @param0	: z	[int] 切片号
    	* @param1	: x	[int] 切片号
    	* @param2	: y	[int] 切片号
    	* @param3	: tablePac	[java.lang.String] 使用表的Pac，比如=53则会在全省所有表获取
    	* @param4	: layerName	[java.lang.String] 生成的矢量切片的图层名
    	* @param5	: tableStartHalfName	[java.lang.String] 搜寻表的前半截名字，比如：b_gis_polygon_qqcg_x+...
        * @param6	: tableEndHalfName	[java.lang.String] 搜寻表的前半截名字，比如：b_gis_polygon_qqcg_x+...
    	* @param6	: boxTableName	[java.lang.String] 用于查询所属切片所在哪个PAC的表，系统表，若不存在会报SystemTableException
    	* @param7	: access	[java.lang.String] 权限值
     * @Return byte[] 返回合并后的矢量切片
    */
    public byte[] selectPacUnionTileByXYZ(int z, int x, int y, String tablePac, String layerName,String groupName,
                                          String tableStartHalfName,String tableEndHalfName,String boxTableName,String access) {
        List<String> pacList = selectPacByLineRowNumFuzzy(x, y, z, boxTableName);
        byte[] mergeBytes = new byte[0];
        String findDataSql = "";
        String general_columns = "";
        String sys_columns = "";
        String colums = "";
        String bbox = "";
        for (String pac1 : pacList) {
            if (pac1.substring(0, tablePac.length()).equals(tablePac)) {
                String tableNameF = tableStartHalfName + pac1;
                if(Globle.GroupPropertiesMap.get(groupName)==null)
                    continue;
                if(Globle.GroupPropertiesMap.get(groupName).getMapTableToGroupEntity().get(tableNameF)==null)
                    continue;
                String tableName=tableNameF+tableEndHalfName;
                if (Globle.TablePropertiesMap.get(tableName) == null ||
                        (!Globle.TablePropertiesMap.get(tableName).getTableType().equals("Vector")))
                    continue;
                log.debug("selectGroupUnionTileByXYZ:tableName:" + tableName + "|x:" + x + "|y:" + y + "|z:" + z);
                if (Globle.TablePropertiesMap.get(tableName) == null || (!Globle.TablePropertiesMap.get(tableName).getTableType().equals("Vector")))
                    continue;
//                int minz = (int) Globle.TablePropertiesMap.get(tableName).getMinz();
//                int maxz = (int) Globle.TablePropertiesMap.get(tableName).getMaxz();
//                if (z < minz || z > maxz)
//                    continue;
                String whereSql = "";
                if (Globle.TablePropertiesMap.get(tableName).getZoomControl())
                    whereSql += " AND zmin<=" + z;
                if (Globle.TablePropertiesMap.get(tableName).getPermissionControl())
                    whereSql += " AND (LEFT(pac," + access.length() + ")='" + access + "' OR pac IS NULL)";
                general_columns = Globle.TablePropertiesMap.get(tableName).getGeneralColumns();
                sys_columns = Globle.TablePropertiesMap.get(tableName).getSysColumns();
                if (colums.equals(""))
                    colums = general_columns + "," + sys_columns;
                if (bbox.equals(""))
                    bbox = "st_transform(TileBBox(" + z + "," + x + "," + y + ")," +
                            Globle.TablePropertiesMap.get(tableName).getSrid() + ")";
                if (findDataSql.equals(""))
                    findDataSql = "SELECT " + colums + ",geom FROM " + tableName + " WHERE " + bbox +
                            " && geom AND del_flag='0' " + whereSql;
                else
                    findDataSql += "UNION ALL SELECT " + colums + ",geom FROM " + tableName + " WHERE " + bbox +
                            " && geom AND del_flag='0' " + whereSql;
            }
        }
        if (findDataSql.equals(""))
            return mergeBytes;
        findDataSql = "(" + findDataSql + ") w WHERE " +
                "geom IS NOT NULL) AS  tile WHERE tile.geom IS NOT NULL";
        String sql = "SELECT ST_AsMVT(tile,'" + layerName + "',4096,'geom') tile FROM (SELECT " + colums + "," +
                "ST_AsMVTGeom(w.geom," + bbox + ",4096, 256, true) AS geom FROM " + findDataSql;
        log.debug(sql);
        mergeBytes = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> rs.getBytes(1));
        return mergeBytes;
    }

    private List<String> selectPacByLineRowNumFuzzy(int x, int y, int z, String boxTableName) {
        if (Globle.TablePropertiesMap.get(boxTableName) == null)
            throw new SystemTableException("tableName="+boxTableName+",数据库中表不存在或未添加进数据目录");
        String bbox="st_transform(TileBBox(" + z + "," + x + "," + y + "),"+ Globle.TablePropertiesMap.get(boxTableName).getSrid()+")";
        String sql = "SELECT pac FROM "+boxTableName+" WHERE "+bbox+"&& geom";
        List<String> locationEntityList = jdbcTemplate.queryForList(sql,String.class);
        return locationEntityList;
    }

    /**
     * @Description TODO 获取切片组切片，切片后联合
    */
    public byte[] selectGroupTileByXYZ(int z, int x, int y, String groupName, String access) {
        if (Globle.GroupPropertiesMap.get(groupName) == null)
            throw new SystemTableException("groupName="+groupName+",数据库中表不存在或未添加进数据目录");
        GroupPropertiesEntity gpe = Globle.GroupPropertiesMap.get(groupName);
        byte[] mergeBytes = new byte[0];
        log.debug("groupName"+groupName+"|x:" + x + "|y:" + y + "|z:" + z);
        for (TableToGroupEntity ttge : gpe.getListTableToGroupEntity()) {
            if (z > ttge.getZmax() || z < ttge.getZmin())
                continue;
            String tableName = ttge.getTableName();
            String layerName = ttge.getLayerName();
            byte[] b = selectTileByXYZ(z, x, y, tableName, layerName, access);
            mergeBytes = ByteArryUtil.ByteMerger(mergeBytes, b);
        }
        return mergeBytes;
    }

    /**
     * @Description TODO 获取切片组切片，联合后切片（只有一个图层，查询组的数据表结构必须一模一样）
    */
    public byte[] selectGroupUnionTileByXYZ(int z, int x, int y, String groupName,String layerName,String access) {
        if (Globle.GroupPropertiesMap.get(groupName) == null)
            throw new SystemTableException("groupName="+groupName+",数据库中表不存在或未添加进数据目录");
        GroupPropertiesEntity gpe = Globle.GroupPropertiesMap.get(groupName);
        byte[] mergeBytes = new byte[0];
        String findDataSql="";
        String general_columns = "";
        String sys_columns = "";
        String colums = "";
        String bbox="";
        log.debug("selectGroupUnionTileByXYZ:groupName"+groupName+"|x:" + x + "|y:" + y + "|z:" + z);
        for (TableToGroupEntity ttge : gpe.getListTableToGroupEntity()) {
            String tableName = ttge.getTableName();
            if (Globle.TablePropertiesMap.get(tableName) == null ||(!Globle.TablePropertiesMap.get(tableName).getTableType().equals("Vector")))
                continue;
            if (z > ttge.getZmax() || z < ttge.getZmin())
                continue;
            int minz = (int) Globle.TablePropertiesMap.get(tableName).getMinz();
            int maxz = (int) Globle.TablePropertiesMap.get(tableName).getMaxz();
            if (z < minz || z > maxz)
                continue;
            String whereSql="";
            if(Globle.TablePropertiesMap.get(tableName).getZoomControl())
                whereSql+=" AND zmin<=" + z;
            if(Globle.TablePropertiesMap.get(tableName).getPermissionControl())
                whereSql+=" AND (LEFT(pac," + access.length() + ")='" + access + "' OR pac IS NULL)";
            general_columns = Globle.TablePropertiesMap.get(tableName).getGeneralColumns();
            sys_columns = Globle.TablePropertiesMap.get(tableName).getSysColumns();
            if(colums.equals(""))
                colums = general_columns + "," + sys_columns;
            if(bbox.equals(""))
                bbox="st_transform(TileBBox(" + z + "," + x + "," + y + "),"+ Globle.TablePropertiesMap.get(tableName).getSrid()+")";
            if(findDataSql.equals(""))
                findDataSql= "SELECT " + colums + ",geom FROM " + tableName + " WHERE "+bbox+
                        " && geom AND del_flag='0' "+whereSql;
            else
                findDataSql+="UNION ALL SELECT " + colums + ",geom FROM " + tableName + " WHERE "+bbox+
                        " && geom AND del_flag='0' "+whereSql;
        }
        if(findDataSql.equals(""))
            return mergeBytes;
        findDataSql="("+findDataSql+") w WHERE " +
                "geom IS NOT NULL) AS  tile WHERE tile.geom IS NOT NULL";
        String sql="SELECT ST_AsMVT(tile,'" + layerName + "',4096,'geom') tile FROM (SELECT " + colums + "," +
                "ST_AsMVTGeom(w.geom,"+bbox+",4096, 256, true) AS geom FROM " +findDataSql;
        mergeBytes = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> rs.getBytes(1));
        return mergeBytes;
    }


}
